using UnityEngine;
using System;
using System.Collections;
using DG.Tweening;
using System.Collections.Generic;
using Pathfinding;
using Pathfinding.Util;

namespace HareGame
{
    public class AIComponent : PoolObj, IEntityIndex
    {
        [Header("移动速度")]
        public float MoveSpeed = 2.5f;

        /// <summary>
        /// 是否到达
        /// </summary>
        [field: SerializeField]
        [field: Header("是否到达")]
        public bool IsReach { get; protected set; }

        public int EntityIndex { get; set; }

        protected AIBase _ai;

        protected Seeker _seeker;

        protected Action _onReach;

        protected bool _needStop;

        [HideInInspector]
        public string Walk = "walk";

        [HideInInspector]
        public string Idle = "idle";

        protected HeadTips _tips;

        [SerializeField]
        protected Animator _anim;

        public override void OnCreate(string poolName)
        {
            base.OnCreate(poolName);

            _ai = GetComponent<AIBase>();
            _seeker = GetComponent<Seeker>();

            _ai.maxSpeed = MoveSpeed;
            _ai.canSearch = false;

            _anim = GetComponentInChildren<Animator>();
            _tips = GetComponentInChildren<HeadTips>();

            GameEntry.Point.AddAI(this);
        }

        /// <summary>
        /// 修改移动速度
        /// </summary>
        /// <param name="speed">速度</param>
        public void ChangeMoveSpeed(float speed)
        {
            _ai.maxSpeed = speed;
        }

        /// <summary>
        /// 显示收益
        /// </summary>
        /// <param name="value">收益</param>
        public virtual void ShowPay(double value)
        {
            _tips.ShowPay((int)value);
        }

        /// <summary>
        /// 设置目标点
        /// </summary>
        /// <param name="targetPos">前往点位</param>
        /// <param name="PathRange">寻路范围</param>
        /// <param name="OnReach">到达回调</param>
        /// <param name="needStop">到终点后是否需要停下</param>
        public virtual void SetPos(PointNode targetPos, PathRange range, Action OnReach = null, bool needStop = true)
        {
            SetPos(targetPos.Position, range, OnReach, needStop);
        }

        /// <summary>
        /// 设置目标点
        /// </summary>
        /// <param name="targetPos">目标坐标</param>
        /// <param name="PathRange">寻路范围</param>
        /// <param name="OnReach">到达回调</param>
        /// <param name="needStop">到终点后是否需要停下</param>
        public virtual void SetPos(Vector3 targetPos, PathRange range, Action OnReach = null, bool needStop = true)
        {
            _onReach = null;
            _ai.enabled = true;
            IsReach = false;
            _onReach = OnReach;
            _needStop = needStop;

            if (range == PathRange.All)
                _seeker.graphMask = -1;
            else
                _seeker.graphMask = 1 << (int)range;

            _ai.SetPath(FleePath.Construct(transform.position, targetPos));
            PlayAnim(Walk);
        }

        public void OnMoveUpdate()
        {
            if (_ai == null || IsReach) return;

            if (_ai.reachedDestination)
            {
                IsReach = true;
                if (_needStop)
                {
                    PlayAnim(Idle);
                    _ai.enabled = false;
                }
                _onReach?.Invoke();
            }
        }

        /// <summary>
        /// 播放动画
        /// </summary>
        /// <param name="clipName">动画片段名</param>
        /// <param name="onComplete">完成动画回调</param>
        public virtual void PlayAnim(string clipName, Action onComplete = null)
        {
            if (_anim == null)
                return;

            _anim.Play(clipName);

            if (onComplete != null)
            {
                float animLength = GetAnimatorLength(clipName) / _anim.speed;
                StartCoroutine(AnimCallBack(animLength, onComplete));
            }
        }

        IEnumerator AnimCallBack(float delay, Action onComplete)
        {
            yield return new WaitForSeconds(delay);
            onComplete.Invoke();
        }

        protected float GetAnimatorLength(string name)
        {
            //动画片段时间长度
            float length = 0;
            AnimationClip[] clips = _anim.runtimeAnimatorController.animationClips;
            foreach (AnimationClip clip in clips)
            {
                if (clip.name.Equals(name))
                {
                    length = clip.length;
                    break;
                }
            }
            return length;
        }
    }
}
